package net.cardgame.orcalecard;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import jp.jma.oraclecard.R;
import net.cardgame.oraclecard.common.CustomAnimationListener;
import net.cardgame.oraclecard.common.CustomImageView;
import net.cardgame.oraclecard.common.ThreadLoadImage;
import net.cardgame.orcalecard.bean.CardBean;
import net.cardgame.orcalecard.bean.DeckBean;
import net.cardgame.orcalecard.bean.SettingApp;
import net.cardgame.orcalecard.pref.SecurePreferences;
import net.cardgame.orcalecard.utils.ConstantValue;
import net.cardgame.orcalecard.utils.KeyboardHelper;
import net.cardgame.orcalecard.utils.Utils;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.SoundPool;
import android.media.SoundPool.OnLoadCompleteListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.TranslateAnimation;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.nineoldandroids.animation.ObjectAnimator;

public class GetCardActivity extends Activity implements OnClickListener,
		OnTouchListener, CustomAnimationListener {
	final static int JUMCARD_STATE = 5, GETCARD_STATE = 4, DEFAULT_STATE = 0;
	ImageView img_Jump, img_bg, img_number_getcard, card0;
	CustomImageView card1, card2, card3, img_ef_ring_getcard;
	RelativeLayout.LayoutParams paramsFront, paramsBehind, paramsCard3;
	ViewGroup parent;
	int deckId, numcards, numberOfCard, state_machine = 0, y_old = 0,
			x_old = 0, _yDelta, state, top_margin;
	SettingApp setting;
	boolean flag = true;
	final int DURATION = 700;
	SoundPool soundPool;
	int height_getcard;
	CardBean cardBean1, cardBean2, cardBean3, cardBean4;
	int cardTotal = 0;
	HashMap<Integer, Integer> mapCardNumber = new HashMap<Integer, Integer>();
	int sound_getcard, sound_jumcard, sound_getcard1, sound_getcard2;
	boolean loaded = false;
	float volume;
	Bitmap mBitmapTemp;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.get_card_activity);
		height_getcard = getResources().getInteger(R.integer.height_getcard);
		parent = (ViewGroup) findViewById(R.id.card_parent);
		setupUI((ViewGroup) findViewById(R.id.parent));
		state_machine = DEFAULT_STATE;
		Bundle bundle = getIntent().getExtras();
		deckId = bundle.getInt("deckId");
		numberOfCard = bundle.getInt("number_of_card");
		if (bundle.containsKey("cardTotal")) {
			cardTotal = bundle.getInt("cardTotal");
		}
		numcards = numberOfCard;
		setting = ConstantValue.getSettingApp(this);
		new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				loadCardBean();
			}
		}).start();
		initView();
		loadImage();
		loadMedia();

	}

	void initView() {
		findViewById(R.id.btnBack_getcard).setOnClickListener(this);
		findViewById(R.id.txtquestion_getcard).clearFocus();
		img_number_getcard = (ImageView) findViewById(R.id.img_number_getcard);
		ImageView btnHelp = (ImageView) findViewById(R.id.btnhelp_getcard);
		btnHelp.setOnClickListener(this);
		img_ef_ring_getcard = (CustomImageView) findViewById(R.id.img_ef_ring_getcard);
		img_ef_ring_getcard.registryListener(this);
		card1 = (CustomImageView) findViewById(R.id.card1_getcard);
		card2 = (CustomImageView) findViewById(R.id.card2_getcard);
		card3 = (CustomImageView) findViewById(R.id.card3_getcard);
		card3.registryListener(this);
		card1.registryListener(this);
		card2.registryListener(this);
		card0 = (ImageView) findViewById(R.id.card0_getcard);
		img_Jump = (ImageView) findViewById(R.id.img_jumpcard_getcard);
		img_bg = (ImageView) findViewById(R.id.img_bg_getcard);
		paramsFront = (RelativeLayout.LayoutParams) card2.getLayoutParams();
		paramsBehind = (RelativeLayout.LayoutParams) card1.getLayoutParams();
		paramsCard3 = (LayoutParams) card3.getLayoutParams();
		top_margin = paramsCard3.topMargin;
		card3.setOnTouchListener(this);
	}

	/**
	 * Setting CardBean1,2,3,4
	 */
	void loadCardBean() {
		// create card bean
		cardBean1 = new CardBean();
		cardBean2 = new CardBean();
		cardBean3 = new CardBean();
		cardBean4 = new CardBean();
		if (deckId == 999) {
			ranDomCardSpecialDeck();
		} else {
			cardBean4.deckId = cardBean3.deckId = cardBean2.deckId = cardBean1.deckId = deckId;
			// Set random cardId
			if (cardTotal == 0)
				cardTotal = 44;
			Random random1 = new Random();
			cardBean1.cardId = random1.nextInt(cardTotal - 1) + 1;
			do {
				Random random = new Random();
				cardBean2.cardId = random.nextInt(cardTotal - 1) + 1;
			} while (cardBean2.cardId == cardBean1.cardId);
			do {
				Random random = new Random();
				cardBean3.cardId = random.nextInt(cardTotal - 1) + 1;
			} while (cardBean3.cardId == cardBean1.cardId
					|| cardBean3.cardId == cardBean2.cardId);
			do {
				Random random = new Random();
				cardBean4.cardId = random.nextInt(cardTotal - 1) + 1;
			} while (cardBean4.cardId == cardBean1.cardId
					|| cardBean4.cardId == cardBean2.cardId
					|| cardBean4.cardId == cardBean3.cardId);
		}
		// Utils.ELog("CardBean1", cardBean1.toString());
		// Utils.ELog("CardBean2", cardBean2.toString());
		// Utils.ELog("CardBean3", cardBean3.toString());
		// Utils.ELog("CardBean4", cardBean4.toString());
	}

	private void ranDomCardSpecialDeck() {
		SecurePreferences appPreferences = new SecurePreferences(this,
				ConstantValue.APP_PREFERENCES,
				ConstantValue.PREFERENCES_SECRET_KEY, true);
		Gson gson = new Gson();
		Type listOfDeckBean = new TypeToken<ArrayList<DeckBean>>() {
		}.getType();
		String listSaved = appPreferences
				.getString(ConstantValue.CONFIG_DECKBEAN_KEY);
		ArrayList<DeckBean> listDeckBean = gson.fromJson(listSaved,
				listOfDeckBean);
		for (int decId : setting.listSpecial) {
			for (DeckBean deckBean : listDeckBean) {
				if (decId == deckBean.deckId) {
					mapCardNumber.put(decId, deckBean.cardNumber);
					break;
				}
			}
		}
		cardBean1 = randomCardBean();
		cardBean2 = randomCardBean();
		cardBean3 = randomCardBean();
		cardBean4 = randomCardBean();
		mapCardNumber.clear();
	}

	private CardBean randomCardBean() {
		CardBean cardBean = new CardBean();
		int size, index, cardNumber;
		size = setting.listSpecial.size();
		do {
			Random random = new Random();
			index = random.nextInt(size);
			cardBean.deckId = setting.listSpecial.get(index);
			cardNumber = mapCardNumber.get(cardBean.deckId);
			cardBean.cardId = random.nextInt(cardNumber - 1) + 1;
		} while ((cardBean.deckId == cardBean1.deckId && cardBean.cardId == cardBean1.cardId)
				|| (cardBean.deckId == cardBean2.deckId && cardBean.cardId == cardBean2.cardId)
				|| (cardBean.deckId == cardBean3.deckId && cardBean.cardId == cardBean3.cardId)
				|| (cardBean.deckId == cardBean4.deckId && cardBean.cardId == cardBean4.cardId));
		return cardBean;
	}

	void getVolume() {
		// Getting the user sound settings
		AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
		float actualVolume = (float) audioManager
				.getStreamVolume(AudioManager.STREAM_MUSIC);
		float maxVolume = (float) audioManager
				.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
		volume = actualVolume / maxVolume;
	}

	void playSound(int soundId) {
		getVolume();
		if (setting.sound) {
			soundPool.play(soundId, volume, volume, 1, 0, 1f);
		}
	}

	void loadMedia() {
		this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
		soundPool = new SoundPool(3, AudioManager.STREAM_MUSIC, 0);
		soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
			@Override
			public void onLoadComplete(SoundPool soundPool, int sampleId,
					int status) {
				loaded = true;
			}
		});
		sound_getcard = soundPool.load(this, R.raw.se_draw_card, 1);
		sound_jumcard = soundPool.load(this, R.raw.se_jump_card, 1);
		sound_getcard1 = soundPool.load(this, R.raw.get_card_001, 1);
		sound_getcard2 = soundPool.load(this, R.raw.get_card_002, 1);
	}

	/**
	 * // * Set encrypt image from SD card to Image View
	 */
	private void loadImage() {
		notifyCardNumber();
		if (deckId == 999) {
			img_bg.setImageResource(R.drawable.bg999);
			card1.setImageResource(R.drawable.c999s);
			card0.setImageResource(R.drawable.c999s);
			card2.setImageResource(R.drawable.c999s);
			mBitmapTemp = BitmapFactory.decodeResource(getResources(),
					R.drawable.c999d);
			img_Jump.setImageResource(R.drawable.c999j);
			return;
		}
		new ThreadLoadImage(this, mHandler,
				ConstantValue.getPathBackgroundByDeckId(this, deckId), img_bg,
				1).start();
		new ThreadLoadImage(this, mHandler, ConstantValue.getPathDeckImage(
				this, deckId, "s"), card1, 2).start();
		new ThreadLoadImage(this, mHandler, ConstantValue.getPathDeckImage(
				this, deckId, "d"), card3, 3).start();
		new ThreadLoadImage(this, mHandler, ConstantValue.getPathDeckImage(
				this, deckId, "j"), img_Jump, 4).start();
	}

	private Handler mHandler = new Handler() {
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case 1:
				img_bg.setImageDrawable((Drawable) msg.obj);
				break;
			case 2:
				card0.setImageDrawable((Drawable) msg.obj);
				card1.setImageDrawable((Drawable) msg.obj);
				card2.setImageDrawable((Drawable) msg.obj);
				break;
			case 3:
				BitmapDrawable drawable = (BitmapDrawable) msg.obj;
				if (drawable != null) {
					mBitmapTemp = drawable.getBitmap();
				}
				break;
			case 4:
				img_Jump.setImageDrawable((Drawable) msg.obj);
				break;
			case 5:
				img_Jump.setVisibility(View.INVISIBLE);
				break;
			case 6:
				ringGetCardAnimation();
				break;
			case 10:
				ImageView imageview = (ImageView) msg.obj;
				if (imageview != null && paramsBehind != null) {
					imageview.setLayoutParams(paramsBehind);
					if (imageview.getId() == R.id.card1_getcard) {
						card2.setLayoutParams(paramsFront);
						parent.bringChildToFront(card2);
					} else {
						card1.setLayoutParams(paramsFront);
						parent.bringChildToFront(card1);
					}
				}
			default:
				break;
			}
		};
	};

	/**
	 * Change number of cards haven't gotten
	 */
	private void notifyCardNumber() {
		if (numberOfCard <= 0) {
			img_number_getcard.setImageResource(R.drawable.draw_this);
		} else
			switch (numberOfCard) {
			case 1:
				img_number_getcard.setImageResource(R.drawable.draw_1);
				break;
			case 2:
				img_number_getcard.setImageResource(R.drawable.draw_2);
				break;
			case 3:
				img_number_getcard.setImageResource(R.drawable.draw_3);
				break;
			case 4:
				img_number_getcard.setImageResource(R.drawable.draw_4);
				break;
			default:
				break;
			}

	}

	Runnable mRunableSleep = new Runnable() {
		@Override
		public void run() {
			// TODO Auto-generated method stub
			mHandler.sendEmptyMessage(6);
		}
	};

	class ThreadCardCut extends Thread {
		ImageView imageView;

		public ThreadCardCut(ImageView imageview) {
			imageView = imageview;
		};

		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			try {
				Thread.sleep(DURATION / 2);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			Message msg = mHandler.obtainMessage(10);
			msg.obj = imageView;
			mHandler.sendMessage(msg);
		}
	}

	private void putListJump() {
		// for (int i = 0; i < 4; i++) {
		// if (listJumcard[i] == 0) {
		// listJumcard[i] = numcards - numberOfCard;
		// break;
		// }
		// }
		int card = numcards - numberOfCard;
		switch (card) {
		case 1:
			cardBean1.isJump = true;
			break;
		case 2:
			cardBean2.isJump = true;
			break;
		case 3:
			cardBean3.isJump = true;
			break;
		case 4:
			cardBean4.isJump = true;
			break;
		default:
			break;
		}
	}

	public void CustomOnclick(View v) {
		if (numberOfCard <= 0) {
			return;
		}
		ringCutCardAnimation();
		if (setting.jumCard) {
			Random random = new Random();
			int i = random.nextInt(20);
			if (i == 5) {
				// Jump card
				numberOfCard--;
				putListJump();
				state_machine = JUMCARD_STATE;
				playSound(sound_jumcard);
				if (mBitmapTemp != null && !mBitmapTemp.isRecycled()) {
					card3.setImageBitmap(mBitmapTemp);
					Animation jump_animation = AnimationUtils.loadAnimation(
							this, R.anim.jumcard_animation);
					card3.startAnimation(jump_animation);
					card3.registryListener(this);
					img_Jump.setVisibility(View.VISIBLE);
				}
				defaultSetupCard();
				notifyCardNumber();
				if (numberOfCard <= 0) {
					gotoResultActivity();
				}
				Timer timer = new Timer();
				timer.schedule(new TimerTask() {

					@Override
					public void run() {
						// TODO Auto-generated method stub
						mHandler.sendEmptyMessage(5);
					}
				}, 1500);
				return;
			} else {
				// Flip card
				playSound(sound_getcard1);
			}
		} else
			playSound(sound_getcard1);
		card3.setImageDrawable(null);
		((CustomImageView) v).registryListener(this);
		new ThreadCardCut((ImageView) v).start();
		ObjectAnimator.ofFloat(v, "translationY", 0, -height_getcard, 0)
				.setDuration(DURATION).start();

	}

	@Override
	public void onClick(View view) {
		// TODO Auto-generated method stub
		if (!flag)
			return;
		switch (view.getId()) {
		case R.id.btnBack_getcard:
			goBack();
			break;
		case R.id.btnhelp_getcard:
			Intent intent = new Intent(this, HelpActivity.class);
			intent.putExtra(HelpActivity.KEY_HELP_INDEX, 9);
			startActivityForResult(intent, 6);
			overridePendingTransition(R.anim.slide_in_right,
					R.anim.slide_out_left);
			break;
		default:
			break;
		}
	}

	private void ringCutCardAnimation() {
		Animation ef_ring = AnimationUtils.loadAnimation(this,
				R.anim.ring_cutcard_animation);
		img_ef_ring_getcard.setImageResource(R.drawable.ef_ring);
		img_ef_ring_getcard.startAnimation(ef_ring);
	}

	private void ringGetCardAnimation() {
		Animation ef_ring = AnimationUtils.loadAnimation(this,
				R.anim.ring_getcard_animation);
		img_ef_ring_getcard.setImageResource(R.drawable.ef_ring);
		img_ef_ring_getcard.startAnimation(ef_ring);
	}

	void defaultSetupCard() {
		state = 2;
		card2.setLayoutParams(paramsFront);
		card1.setLayoutParams(paramsBehind);
		parent.bringChildToFront(card2);
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		// TODO Auto-generated method stub
		if (numberOfCard <= 0)
			return false;
		final int Y = (int) event.getRawY();
		switch (event.getAction() & MotionEvent.ACTION_MASK) {
		case MotionEvent.ACTION_DOWN:
			KeyboardHelper.hideSoftKeyboard(this);
			findViewById(R.id.txtquestion_getcard).clearFocus();
			RelativeLayout.LayoutParams lParams2 = (RelativeLayout.LayoutParams) v
					.getLayoutParams();
			_yDelta = Y - lParams2.topMargin;
			y_old = Y;
			x_old = (int) event.getRawX();
			break;
		case MotionEvent.ACTION_UP:
			notifyCardNumber();
			int x = (int) event.getRawX();

			if (Math.abs(Y - y_old) < 10 && Math.abs(x - x_old) < 10) {
				if (state == 1) {
					state = 2;
					CustomOnclick(card1);
				} else {
					state = 1;
					CustomOnclick(card2);
				}
			} else {
				v.setLayoutParams(paramsCard3);
				int s = Y - y_old;
				int speed = 50;
				int t = Math.abs(100 * s / speed);
				TranslateAnimation animation = new TranslateAnimation(0, 0, 0,
						-s);
				animation.setDuration(t);
				card3.startAnimation(animation);
			}

			if (y_old - Y >= paramsCard3.height / 2) {// perform get Card
				if (numberOfCard <= 0)
					return true;
				numberOfCard--;
				if (numberOfCard <= 0) {
					gotoResultActivity();
				}
				notifyCardNumber();
				Animation getcard_animation = AnimationUtils.loadAnimation(
						this, R.anim.getcard_animation);
				card3.startAnimation(getcard_animation);
				mHandler.postDelayed(mRunableSleep, 150);
				state_machine = GETCARD_STATE;
				playSound(sound_getcard);
			}
			break;
		case MotionEvent.ACTION_MOVE:
			if (mBitmapTemp != null && !mBitmapTemp.isRecycled()
					&& card3.getDrawable() == null) {
				card3.setImageBitmap(mBitmapTemp);
			}
			RelativeLayout.LayoutParams layoutParams = (LayoutParams) v
					.getLayoutParams();
			layoutParams.topMargin = Y - _yDelta;
			layoutParams.leftMargin = -250;
			layoutParams.rightMargin = -250;
			layoutParams.bottomMargin = -250;
			v.setLayoutParams(layoutParams);
			if (y_old - Y >= paramsCard3.height / 2) {
				img_number_getcard.setImageResource(R.drawable.draw_this);
			} else {
				notifyCardNumber();
			}
			break;
		default:
			break;
		}
		return true;
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		flag = true;
		overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);
	}

	public void setupUI(View view) {
		// Set up touch listener for non-text box views to hide keyboard.
		if (!(view instanceof EditText)) {

			view.setOnTouchListener(new OnTouchListener() {

				public boolean onTouch(View v, MotionEvent event) {
					v.requestFocus();
					KeyboardHelper.hideSoftKeyboard(GetCardActivity.this);
					return false;
				}

			});
		}

		// If a layout container, iterate over children and seed recursion.
		if (view instanceof ViewGroup) {

			for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {

				View innerView = ((ViewGroup) view).getChildAt(i);

				setupUI(innerView);
			}
		}
	}

	void gotoResultActivity() {
		EditText textInput = (EditText) findViewById(R.id.txtquestion_getcard);
		final String text = textInput.getText().toString();
		Timer timer = new Timer();
		timer.schedule(new TimerTask() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				Intent intent = new Intent(GetCardActivity.this,
						ResultActivity.class);
				Bundle bundle = getIntent().getExtras();
				intent.putExtra("cardBean1", cardBean1);
				intent.putExtra("cardBean2", cardBean2);
				intent.putExtra("cardBean3", cardBean3);
				intent.putExtra("cardBean4", cardBean4);
				bundle.putString("text_input", text);
				intent.putExtras(bundle);
				startActivity(intent);
				overridePendingTransition(R.anim.slide_in_right,
						R.anim.slide_out_left);
				GetCardActivity.this.finish();
			}
		}, 1000);

	}

	@Override
	public synchronized void onEndAnimation(ImageView imageview) {
		// TODO Auto-generated method stub
		if (imageview.getId() == R.id.img_ef_ring_getcard) {
			imageview.setImageDrawable(null);
			return;
		}
		if (imageview.getId() == R.id.card1_getcard
				|| imageview.getId() == R.id.card2_getcard) {
			playSound(sound_getcard2);
		}

		switch (state_machine) {
		case JUMCARD_STATE:
			imageview.setImageDrawable(null);
			state_machine = DEFAULT_STATE;
			img_Jump.setVisibility(View.INVISIBLE);
			notifyCardNumber();
			break;
		case DEFAULT_STATE:
			if (imageview.getId() == R.id.card3_getcard) {
				imageview.setImageDrawable(null);
				RelativeLayout.LayoutParams layoutParams = (LayoutParams) imageview
						.getLayoutParams();
				layoutParams.topMargin = top_margin;
				layoutParams.leftMargin = -250;
				layoutParams.rightMargin = -250;
				layoutParams.bottomMargin = -250;
				imageview.setLayoutParams(layoutParams);
				return;
			}
			imageview.setLayoutParams(paramsBehind);
			break;
		case GETCARD_STATE:
			state_machine = DEFAULT_STATE;
			if (imageview.getId() == R.id.card3_getcard) {
				imageview.setImageDrawable(null);
				RelativeLayout.LayoutParams layoutParams = (LayoutParams) imageview
						.getLayoutParams();
				layoutParams.topMargin = top_margin;
				layoutParams.leftMargin = -250;
				layoutParams.rightMargin = -250;
				layoutParams.bottomMargin = -250;
				imageview.setLayoutParams(layoutParams);
				imageview.setImageDrawable(null);
				// ringGetCardAnimation();
				return;
			}
			break;
		default:
			break;
		}

	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
			goBack();
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}

	private void goBack() {
		if (mBitmapTemp != null && !mBitmapTemp.isRecycled()) {
			mBitmapTemp.recycle();
		}
		Intent intent = new Intent(this, SplashDeckBeanActivity.class);
		intent.putExtras(getIntent().getExtras());
		startActivity(intent);
		overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);
		this.finish();
	}

}
